#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
增强权限装饰器 - 实现细粒度权限控制
"""

from functools import wraps
from flask import jsonify
from flask_jwt_extended import verify_jwt_in_request, get_jwt_identity, get_jwt
from backend.models.user import User
from backend.models.role import Role
from backend.models.permission import Permission

def require_roles(*required_roles):
    """
    角色权限装饰器
    
    Args:
        required_roles: 需要的角色列表，用户拥有其中任一角色即可访问
    
    Usage:
        @require_roles('admin', 'teacher')
        def some_api():
            pass
    """
    def decorator(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            try:
                # 验证JWT
                verify_jwt_in_request()
                
                # 获取当前用户ID
                current_user_id = get_jwt_identity()
                if not current_user_id:
                    return jsonify({
                        'success': False,
                        'message': '未登录或登录已过期'
                    }), 401
                
                # 获取JWT中的角色信息
                claims = get_jwt()
                user_roles = claims.get('roles', [])
                
                # 检查角色权限
                if not any(role in user_roles for role in required_roles):
                    return jsonify({
                        'success': False,
                        'message': f'权限不足，需要角色: {", ".join(required_roles)}'
                    }), 403
                
                return fn(*args, **kwargs)
                
            except Exception as e:
                return jsonify({
                    'success': False,
                    'message': f'权限验证失败: {str(e)}'
                }), 500
        
        return wrapper
    return decorator

def require_permissions(*required_permissions):
    """
    权限装饰器
    
    Args:
        required_permissions: 需要的权限列表，用户拥有其中任一权限即可访问
    
    Usage:
        @require_permissions('user:read', 'user:write')
        def some_api():
            pass
    """
    def decorator(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            try:
                # 验证JWT
                verify_jwt_in_request()
                
                # 获取当前用户ID
                current_user_id = get_jwt_identity()
                if not current_user_id:
                    return jsonify({
                        'success': False,
                        'message': '未登录或登录已过期'
                    }), 401
                
                # 查询用户
                user = User.query.get(current_user_id)
                if not user:
                    return jsonify({
                        'success': False,
                        'message': '用户不存在'
                    }), 404
                
                # 获取用户所有权限
                user_permissions = []
                for role in user.roles:
                    for permission in role.permissions:
                        if permission.code not in user_permissions:  # 修复：使用code而不是name
                            user_permissions.append(permission.code)
                
                # 检查权限
                if not any(perm in user_permissions for perm in required_permissions):
                    return jsonify({
                        'success': False,
                        'message': f'权限不足，需要权限: {", ".join(required_permissions)}'
                    }), 403
                
                return fn(*args, **kwargs)
                
            except Exception as e:
                return jsonify({
                    'success': False,
                    'message': f'权限验证失败: {str(e)}'
                }), 500
        
        return wrapper
    return decorator

def require_self_or_admin(user_id_field='user_id'):
    """
    自己或管理员权限装饰器
    用户只能访问自己的数据，除非是管理员
    
    Args:
        user_id_field: 请求参数中用户ID的字段名
    
    Usage:
        @require_self_or_admin('target_user_id')
        def some_api():
            pass
    """
    def decorator(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            try:
                # 验证JWT
                verify_jwt_in_request()
                
                # 获取当前用户ID
                current_user_id = get_jwt_identity()
                if not current_user_id:
                    return jsonify({
                        'success': False,
                        'message': '未登录或登录已过期'
                    }), 401
                
                # 获取JWT中的角色信息
                claims = get_jwt()
                user_roles = claims.get('roles', [])
                
                # 管理员可以访问所有数据
                if 'admin' in user_roles:
                    return fn(*args, **kwargs)
                
                # 获取目标用户ID
                from flask import request
                target_user_id = None
                
                if request.method == 'GET':
                    target_user_id = request.args.get(user_id_field)
                else:
                    data = request.get_json() or {}
                    target_user_id = data.get(user_id_field)
                
                # 检查是否访问自己的数据
                if str(target_user_id) != str(current_user_id):
                    return jsonify({
                        'success': False,
                        'message': '只能访问自己的数据'
                    }), 403
                
                return fn(*args, **kwargs)
                
            except Exception as e:
                return jsonify({
                    'success': False,
                    'message': f'权限验证失败: {str(e)}'
                }), 500
        
        return wrapper
    return decorator

def require_student_parent(student_id_field='student_id'):
    """
    学生家长权限装饰器
    只有学生的家长才能访问学生相关数据
    
    Args:
        student_id_field: 请求参数中学生ID的字段名
    
    Usage:
        @require_student_parent('student_id')
        def some_api():
            pass
    """
    def decorator(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            try:
                # 验证JWT
                verify_jwt_in_request()
                
                # 获取当前用户ID
                current_user_id = get_jwt_identity()
                if not current_user_id:
                    return jsonify({
                        'success': False,
                        'message': '未登录或登录已过期'
                    }), 401
                
                # 获取JWT中的角色信息
                claims = get_jwt()
                user_roles = claims.get('roles', [])
                
                # 管理员、教师、医生可以访问所有学生数据
                if any(role in user_roles for role in ['admin', 'teacher', 'doctor']):
                    return fn(*args, **kwargs)
                
                # 获取目标学生ID
                from flask import request
                target_student_id = None
                
                if request.method == 'GET':
                    target_student_id = request.args.get(student_id_field)
                else:
                    data = request.get_json() or {}
                    target_student_id = data.get(student_id_field)
                
                if not target_student_id:
                    return jsonify({
                        'success': False,
                        'message': '学生ID不能为空'
                    }), 400
                
                # 检查是否是学生的家长
                from backend.models.student_parent_binding import StudentParentBinding
                binding = StudentParentBinding.query.filter_by(
                    user_id=current_user_id,
                    student_id=target_student_id,
                    status='active'
                ).first()
                
                if not binding:
                    return jsonify({
                        'success': False,
                        'message': '只能访问您绑定的学生数据'
                    }), 403
                
                return fn(*args, **kwargs)
                
            except Exception as e:
                return jsonify({
                    'success': False,
                    'message': f'权限验证失败: {str(e)}'
                }), 500
        
        return wrapper
    return decorator

# 预定义常用装饰器
admin_required = require_roles('admin')
teacher_required = require_roles('admin', 'teacher')
doctor_required = require_roles('admin', 'doctor')
parent_required = require_roles('admin', 'parent')
staff_required = require_roles('admin', 'teacher', 'doctor', 'operator')

# 预定义权限装饰器
user_read_required = require_permissions('user:read')
user_write_required = require_permissions('user:write')
student_read_required = require_permissions('student:read')
student_write_required = require_permissions('student:write')
intervention_read_required = require_permissions('intervention:read')
intervention_write_required = require_permissions('intervention:write')
report_read_required = require_permissions('report:read')
system_manage_required = require_permissions('system:manage')

def require_data_access(resource_id_field='id'):
    """
    数据访问权限装饰器
    根据用户角色控制数据访问范围：
    - admin: 可访问所有数据
    - teacher/doctor/assistant: 可访问部门数据
    - parent: 只能访问绑定学生的数据
    - registered_user: 只能访问自己的数据
    
    Args:
        resource_id_field: 资源ID字段名
    
    Usage:
        @require_data_access('student_id')
        def get_student_info():
            pass
    """
    def decorator(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            try:
                # 获取当前用户
                current_user_id = get_jwt_identity()
                if not current_user_id:
                    return jsonify({
                        'success': False,
                        'message': '用户未登录'
                    }), 401
                
                # 获取JWT中的角色信息
                claims = get_jwt()
                user_roles = claims.get('roles', [])
                
                # 管理员可以访问所有数据
                if 'admin' in user_roles:
                    return fn(*args, **kwargs)
                
                # 医生可以访问所有数据
                if 'doctor' in user_roles:
                    return fn(*args, **kwargs)
                
                # 教师和助理可以访问部门数据（这里简化为所有数据，实际应该根据部门过滤）
                if any(role in user_roles for role in ['teacher', 'assistant']):
                    return fn(*args, **kwargs)
                
                # 家长只能访问绑定学生的数据
                if 'parent' in user_roles:
                    # 这里需要检查学生绑定关系，暂时允许访问
                    return fn(*args, **kwargs)
                
                # 注册用户只能访问自己的数据
                if 'registered_user' in user_roles:
                    # 这里需要检查资源所有权，暂时允许访问
                    return fn(*args, **kwargs)
                
                # 访客无法访问
                return jsonify({
                    'success': False,
                    'message': '权限不足'
                }), 403
                
            except Exception as e:
                return jsonify({
                    'success': False,
                    'message': f'权限验证失败: {str(e)}'
                }), 500
        
        return wrapper
    return decorator
